import asyncio
import logging
import signal
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger

logger = logging.getLogger(__name__)


class TaskScheduler:
    def __init__(self, max_concurrent_tasks: int):
        self.scheduler = AsyncIOScheduler()
        self.loop = asyncio.get_event_loop()
        self.max_concurrent_tasks = max_concurrent_tasks
        self._register_signals()

    def _register_signals(self):
        """注册信号处理程序，处理 Ctrl + C 等终止信号。"""
        for sig in (signal.SIGINT, signal.SIGTERM):
            try:
                self.loop.add_signal_handler(sig, self._handle_shutdown_signal)
            except NotImplementedError:
                logger.warning(f"Signal handling is not supported on this platform.")

    def _handle_shutdown_signal(self):
        """处理信号，优雅关闭调度器"""
        logger.info("Received shutdown signal, stopping scheduler...")
        # 使用 `loop.create_task()` 调度 `stop()` 异步任务
        self.loop.create_task(self.stop())

    async def stop(self):
        """停止调度器并等待所有任务完成"""
        if self.scheduler.running:
            logger.info("Stopping scheduler...")
            self.scheduler.shutdown(wait=False)
            logger.info("Scheduler stopped.")
        else:
            logger.info("Scheduler was already stopped or not running.")

        # 等待所有任务完成后停止事件循环
        logger.info("Waiting for all tasks to complete...")
        await asyncio.sleep(1)  # 假设有任务在后台执行，这里可以是实际的等待任务完成的逻辑

        # 停止事件循环，退出程序
        self.loop.stop()

    def start(self):
        """启动调度器"""
        self.scheduler.start()
        logger.info("Scheduler started.")

    def add_task(self, task, interval: int):
        """将任务添加到调度器"""
        self.scheduler.add_job(
            task.run,  # 直接传递 task.run，不需要 args
            trigger=IntervalTrigger(seconds=interval)
        )


class TaskEntry:
    def __init__(self, task_name: str):
        self.task_name = task_name

    async def run(self):
        """任务的执行方法"""
        logger.info(f"Task {self.task_name} started.")
        await asyncio.sleep(2)  # 模拟异步工作
        logger.info(f"Task {self.task_name} completed.")


async def main():
    logging.basicConfig(level=logging.INFO)

    # 创建任务调度器，限制最大并发数为 5
    scheduler = TaskScheduler(max_concurrent_tasks=5)

    # 创建任务
    tasks = [TaskEntry(task_name=f"task_{i}") for i in range(10)]

    # 添加任务到调度器，每隔 5 秒触发一次
    for task in tasks:
        scheduler.add_task(task, interval=5)

    # 启动调度器
    scheduler.start()

    # 持续运行直到收到信号停止
    try:
        while True:
            await asyncio.sleep(1)
    except KeyboardInterrupt:
        logger.info("Received KeyboardInterrupt. Stopping...")
        await scheduler.stop()


if __name__ == "__main__":
    asyncio.run(main())
